package org.osmdroid.tileprovider.modules;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;

import org.osmdroid.tileprovider.MapTile;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;

public class MBTilesFileArchive implements IArchiveFile {

    private static final Logger logger = LoggerFactory.getLogger(MBTilesFileArchive.class);

    private final SQLiteDatabase mDatabase;

    // TABLE tiles (zoom_level INTEGER, tile_column INTEGER, tile_row INTEGER,
    // tile_data BLOB);
    public final static String TABLE_TILES = "tiles";
    public final static String COL_TILES_ZOOM_LEVEL = "zoom_level";
    public final static String COL_TILES_TILE_COLUMN = "tile_column";
    public final static String COL_TILES_TILE_ROW = "tile_row";
    public final static String COL_TILES_TILE_DATA = "tile_data";

    private MBTilesFileArchive(final SQLiteDatabase pDatabase) {
        mDatabase = pDatabase;
    }

    public static MBTilesFileArchive getDatabaseFileArchive(final File pFile) throws SQLiteException {
        return new MBTilesFileArchive(SQLiteDatabase.openDatabase(pFile.getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY));
    }

    @Override
    public InputStream getInputStream(final ITileSource pTileSource, final MapTile pTile) {
        try {
            InputStream ret = null;
            final String[] tile = { COL_TILES_TILE_DATA };
            final String[] xyz = { Integer.toString(pTile.getX()), Double.toString(Math.pow(2, pTile.getZoomLevel()) - pTile.getY() - 1) // Use
                                                                                                                                         // Google
                                                                                                                                         // Tiling
                                                                                                                                         // Spec
                    , Integer.toString(pTile.getZoomLevel()) };

            final Cursor cur = mDatabase.query(TABLE_TILES, tile, "tile_column=? and tile_row=? and zoom_level=?", xyz, null, null, null);

            if (cur.getCount() != 0) {
                cur.moveToFirst();
                ret = new ByteArrayInputStream(cur.getBlob(0));
            }
            cur.close();
            if (ret != null) {
                return ret;
            }
        } catch (final Throwable e) {
            logger.warn("Error getting db stream: " + pTile, e);
        }

        return null;
    }

    @Override
    public String toString() {
        return "DatabaseFileArchive [mDatabase=" + mDatabase.getPath() + "]";
    }

    @Override
    public void close() {
        mDatabase.close();
    }

}
